/*
PearReview - The peer review assistant.
Copyright (C) 2009  Dimitrij Pankratz, Anton Musichin
http://www.pearreview.com, info@pearreview.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package com.pearreview.ui.clock;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Serializable;
import java.util.Calendar;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;

public class ScribeClock extends JPanel {

	private static final long serialVersionUID = 208211700201832978L;
	
	private JLabel clockLabel;
	private PlayButton startBtn;
	private JButton stopBtn;
	private long startTime = System.currentTimeMillis();
	private long pauseTime;
	private long plannedDuration = 0;
	private String plannedDurationStr = "00:00:00";
	private boolean started = false;
	private boolean paused = false;
	
	private Timer timer = new Timer(100, new RefreshActionListener());
	
	public ScribeClock () {
		setOpaque(false);
		setMaximumSize(new Dimension(Short.MAX_VALUE, 35));
		
		clockLabel = new JLabel("00:00:00 / 00:00:00");
		clockLabel.setFont(new Font("Tahoma", Font.PLAIN, 14));
		
		startBtn = new PlayButton();
		startBtn.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				if (paused || !started) {
					startTimer();
				} else {
					pauseTimer();
				}
			}
			
		});
		
		stopBtn = new StopButton();
		stopBtn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				stopTimer();
				
			}
		});

		add(startBtn);
		add(stopBtn);
		add(clockLabel);
	}
	
	public static long getMillisecondsDifference(Calendar start, Calendar end) {
		return TimeDiff.getInstance(start, end, true).totalMilliSeconds;
	}
	
	public void setStartEndTime(Calendar start, Calendar end) {
		plannedDuration = getMillisecondsDifference(start, end);
		plannedDurationStr = millisToString(plannedDuration);
		refreshTimer();
	}
	
	public long getPlannedTime() {
		return plannedDuration;
	}
	
	public void setPlannedTime(long time) {
		plannedDuration = time;
		plannedDurationStr = millisToString(plannedDuration);
		refreshTimer();
	}
	
	public void pauseTimer() {
		if(!started)
			return;
		paused = true;
		startBtn.setPaused(false);
		pauseTime = System.currentTimeMillis();
		timer.stop();
		refreshTimer();
	}
	
	public void startTimer() {
		if (started && paused) 
			startTime += System.currentTimeMillis() - pauseTime;
		else if(!started)
			startTime = System.currentTimeMillis();
		
		paused = false;
		started = true;
		startBtn.setPaused(true);
		
		timer.start();
		refreshTimer();
	}
	
	public void refreshTimer() {
		long passedTime = getPassedTime();
		
		if(plannedDuration < 0) {
			clockLabel.setText(millisToString(passedTime));
		} else if (passedTime/1000 > plannedDuration/1000) {
			clockLabel.setText("<html><font color='red'>" +
					millisToString(passedTime) +
					"</font>" +
					" / " + plannedDurationStr + "</html>");
		} else {
			clockLabel.setText(
					millisToString(passedTime) + 
					" / " + plannedDurationStr);
		}
	}
	
	public void stopTimer() {
		started = false;
		paused = false;
		startBtn.setPaused(false);
		timer.stop();
		startTime = System.currentTimeMillis();
		refreshTimer();
	}
	
	public String millisToString(long millisTime) {
		millisTime /= 1000;
		int seconds = (int)(millisTime%60); millisTime /= 60;
		int minutes = (int)(millisTime%60); millisTime /= 60;
		int hours = (int)(millisTime%60);
		
		String secondsStr = Integer.toString(seconds); 
		if (seconds < 10)
			secondsStr = "0" + secondsStr;
		
		String minutesStr = Integer.toString(minutes); 
		if (minutes < 10)
			minutesStr = "0" + minutesStr;
		
		String hoursStr = Integer.toString(hours); 
		if (hours < 10)
			hoursStr = "0" + hoursStr;
		
		return hoursStr + ":" + minutesStr + ":" + secondsStr;
	}
	
	public long getPassedTime() {
		long passed = 0;
		if(started)
			passed = System.currentTimeMillis() - startTime;
		if(started && paused)
			passed -= System.currentTimeMillis() - pauseTime;
		return passed;
	}
	
	public void setPassedTime(long passed) {
		startTime = System.currentTimeMillis() - passed;
		
		if(!started) {
			started = true;
			paused = true;
		}
		
		pauseTime = System.currentTimeMillis();
		
		refreshTimer();
	}
	
	public boolean isPaused() {
		return paused;
	}
	
	public boolean isRunning() {
		return started && !paused;
	}
	
	private static class TimeDiff {
		public long totalMilliSeconds;
		
		public static TimeDiff getInstance(Calendar t1, Calendar t2, 
				boolean onlyClock) {
			Calendar clone1 = (Calendar) t1.clone();
			
			//only time, put the date away
			if(onlyClock) {
				clone1.set(t2.get(Calendar.YEAR), 
						t2.get(Calendar.MONTH),
						t2.get(Calendar.DAY_OF_MONTH));
				if(clone1.after(t2)) {
					t2.add(Calendar.DAY_OF_MONTH, 1);
				}
			}
			
			TimeDiff td = new TimeDiff();
			
			//calculate seconds, minutes and hours
			td.totalMilliSeconds = 
					Math.abs(t2.getTimeInMillis() - clone1.getTimeInMillis());
			
			return td;
		}
	}
	
	private class RefreshActionListener implements ActionListener, Serializable{
		private static final long serialVersionUID = 7203173710156181411L;
		@Override
		public void actionPerformed(ActionEvent e) {
			if(started && !paused)
				refreshTimer();
		}
	}
	
	/**
	 * If clock was started, the this will be started or paused
	 */
	@Override
	public void setEnabled(boolean enabled) {
		startBtn.setEnabled(enabled);
		stopBtn.setEnabled(enabled);
		super.setEnabled(enabled);
		
		if(started && !paused && !enabled)
			pauseTimer();
		else if(started && paused && enabled)
			startTimer();
			
	}
}
